\section{Ещё о возвращаемых результатах}

\myindex{x86!\Registers!EAX}
Результат выполнения функции в x86 обычно возвращается
\footnote{\Seealso: MSDN: Return Values (C++): \href{http://go.yurichev.com/17258}{MSDN}}
через регистр \EAX, а если результат имеет тип байт или символ (\Tchar), 
то в самой младшей части \EAX~--- \AL. Если функция возвращает число с плавающей запятой, 
то будет использован регистр FPU \ST{0}.
\myindex{ARM!\Registers!R0}
В ARM обычно результат возвращается в регистре \Reg{0}.

\subsection{Попытка использовать результат функции возвращающей \Tvoid}

Кстати, что будет, если возвращаемое значение в функции \main объявлять не как \Tint, а как \Tvoid?
Т.н. startup-код вызывает \main примерно так:

\begin{lstlisting}[style=customasmx86]
push envp
push argv
push argc
call main
push eax
call exit
\end{lstlisting}

Иными словами:

\begin{lstlisting}[style=customc]
exit(main(argc,argv,envp));
\end{lstlisting}

Если вы объявите \main как \Tvoid, и ничего не будете возвращать явно (при помощи выражения \IT{return}), то в единственный аргумент exit() попадет то, что лежало в регистре \EAX на момент выхода из \main.
Там, скорее всего, будет какие-то случайное число, оставшееся от работы вашей функции. Так что код завершения программы будет псевдослучайным.

Мы можем это проиллюстрировать.
Заметьте, что у функции \main тип возвращаемого значения именно \Tvoid{}:

\begin{lstlisting}[style=customc]
#include <stdio.h>

void main()
{
	printf ("Hello, world!\n");
};
\end{lstlisting}

Скомпилируем в Linux.

\myindex{puts() вместо printf()}
GCC 4.8.1 заменила \printf на \puts 
(мы видели это прежде: \myref{puts}), но это нормально, потому что \puts возвращает количество
выведенных символов, так же как и \printf.
Обратите внимание на то, что \EAX не обнуляется перед выходом их \main.
Это значит что \EAX перед выходом из \main содержит то, что \puts оставляет там.


\begin{lstlisting}[caption=GCC 4.8.1,style=customasmx86]
.LC0:
	.string	"Hello, world!"
main:
	push	ebp
	mov	ebp, esp
	and	esp, -16
	sub	esp, 16
	mov	DWORD PTR [esp], OFFSET FLAT:.LC0
	call	puts
	leave
	ret
\end{lstlisting}

\myindex{bash}
Напишем небольшой скрипт на bash, показывающий статус возврата (\q{exit status} или \q{exit code}):

\begin{lstlisting}[caption=tst.sh]
#!/bin/sh
./hello_world
echo $?
\end{lstlisting}

И запустим:

\begin{lstlisting}
$ tst.sh 
Hello, world!
14
\end{lstlisting}

14 это как раз количество выведенных символов.
Количество выведенных символов \textit{проскальзывает} из \printf{} через \TT{EAX}/\TT{RAX} в \q{exit code}.

\myindex{Hex-Rays}
Кстати, когда в Hex-Rays мы разбираем C++ код, нередко можно наткнуться на ф-цию, которая заканчивается
деструктором какого-либо класса:

\begin{lstlisting}
...

call    ??1CString@@QAE@XZ ; CString::~CString(void)
mov     ecx, [esp+30h+var_C]
pop     edi
pop     ebx
mov     large fs:0, ecx
add     esp, 28h
retn
\end{lstlisting}

По стандарту С++, деструкторы ничего не возвращают, но когда Hex-Rays об не знает, и думает что и десктрутор,
и эта ф-ция по умолчанию возвращает \Tint, то на выходе получается такой код:

\begin{lstlisting}[style=customc]
...

	return CString::~CString(&Str);
}
\end{lstlisting}

\subsection{Что если не использовать результат функции?}

\printf возвращает количество успешно выведенных символов, но результат работы этой функции 
редко используется на практике.

Можно даже явно вызывать функции, чей смысл именно в возвращаемых значениях, но явно не использовать их:

\begin{lstlisting}[style=customc]
int f()
{
    // пропускаем первые 3 случайных значения:
    rand();
    rand();
    rand();
    // и используем §4-е§:
    return rand();
};
\end{lstlisting}

Результат работы rand() остается в \EAX во всех четырех случаях.
Но в первых трех случаях значение, лежащее в \EAX, просто не используется.

\subsection{Возврат структуры}

\myindex{\CLanguageElements!return}
Вернемся к тому факту, что возвращаемое значение остается в регистре \EAX.
Вот почему старые компиляторы Си не способны создавать функции, возвращающие нечто большее, нежели 
помещается в один регистр (обычно тип \Tint), а когда нужно, приходится возвращать через указатели, указываемые 
в аргументах.
Так что как правило, если функция должна вернуть несколько значений, она возвращает только одно, 
а остальные~--- через указатели.
Хотя позже и стало возможным, вернуть, скажем, целую структуру, но этот метод до сих пор не 
очень популярен. 
Если функция должна вернуть структуру, вызывающая функция должна сама, скрыто и прозрачно для программиста, 
выделить место и передать указатель на него в качестве первого аргумента. Это почти то же самое 
что и сделать это вручную, но компилятор прячет это.

Небольшой пример:

\lstinputlisting[style=customc]{patterns/06_return_results/6_1.c}

\dots получим (MSVC 2010 \Ox):

\lstinputlisting[style=customasmx86]{patterns/06_return_results/6_1.asm}

\GTT{\$T3853} это имя внутреннего макроса для передачи указателя на структуру.

\myindex{\CLanguageElements!C99}
Этот пример можно даже переписать, используя расширения C99:

\lstinputlisting[style=customc]{patterns/06_return_results/6_1_C99.c}

\lstinputlisting[caption=GCC 4.8.1,style=customasmx86]{patterns/06_return_results/6_1_C99.asm}

Как видно, функция просто заполняет поля в структуре, выделенной вызывающей функцией. 
Как если бы передавался просто указатель на структуру.
Так что никаких проблем с эффективностью нет.

